/* Includes ------------------------------------------------------------------*/
#include "Led7Seg.h"
#include "PWM.h"
#include "SystemTick.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#define SEG_DP_ENABLE       0x80
#define ALL_SEG_DISABLE     0x00
const u8            c_LedDecode[16] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71};

GPIO_TypeDef*       s_LedActivePort[TOTAL_ACTIVE_LED] = {LED_TRAM_PORT, LED_CHUC_PORT, LED_DONVI_PORT, LED_REV_PORT};  
GPIO_Pin_TypeDef    s_LedActivePin[TOTAL_ACTIVE_LED] = {LED_TRAM_PINS, LED_CHUC_PINS, LED_DONVI_PINS, LED_REV_PINS};  
GPIO_TypeDef*       s_SegmentPort[TOTAL_SEGMENT] = {SEG_A_PORT, SEG_B_PORT, SEG_C_PORT, SEG_D_PORT, SEG_E_PORT, SEG_F_PORT, SEG_G_PORT, SEG_DP_PORT};
GPIO_Pin_TypeDef    s_SegmentPin[TOTAL_SEGMENT] = {SEG_A_PINS, SEG_B_PINS, SEG_C_PINS, SEG_D_PINS, SEG_E_PINS, SEG_F_PINS, SEG_G_PINS, SEG_DP_PINS};

u8      s_Led7SegDecoded[TOTAL_ACTIVE_LED];
bool    s_SWPressed[TOTAL_ACTIVE_LED] = {FALSE, FALSE, FALSE, FALSE};
bool    s_SWPressedOld[TOTAL_ACTIVE_LED] = {FALSE, FALSE, FALSE, FALSE};
u8      s_CurActiveIndex = 0;
bool    s_DispSegDp = TRUE;
bool    s_DispAllSeg = TRUE;


/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/

void Led7Seg_Init(void)
{
    u8 i;
    // Initialize I/Os in Output Mode
    for (i=0; i<TOTAL_ACTIVE_LED; i++)
    {
        GPIO_Init(s_LedActivePort[i], s_LedActivePin[i], GPIO_MODE_OUT_OD_LOW_SLOW);
        GPIO_WriteHigh(s_LedActivePort[i], s_LedActivePin[i]);

        s_SWPressed[i] = FALSE;
    }

    for (i=0; i<TOTAL_SEGMENT; i++)
    {
        GPIO_Init(s_SegmentPort[i], s_SegmentPin[i], GPIO_MODE_OUT_OD_HIZ_SLOW);
        GPIO_WriteHigh(s_SegmentPort[i], s_SegmentPin[i]);
    }

    // init SW input
    GPIO_Init(SW_IN_PORT, SW_IN_PIN, GPIO_MODE_IN_PU_NO_IT);

    Led7Seg_Push(000);
}


void Led7Seg_SetLedON(u8 iCurLed)
{
    if (TOTAL_ACTIVE_LED > iCurLed)
    {
        GPIO_WriteLow(s_LedActivePort[iCurLed], s_LedActivePin[iCurLed]);
    }
}


void Led7Seg_SetLedOFF(u8 iCurLed)
{
    if (TOTAL_ACTIVE_LED > iCurLed)
    {
        GPIO_WriteHigh(s_LedActivePort[iCurLed], s_LedActivePin[iCurLed]);
    }
}


void Led7Seg_SetAllLedOFF(void)
{
    u8 i;
    for (i=0; i<TOTAL_ACTIVE_LED; i++)
    {
        GPIO_WriteHigh(s_LedActivePort[i], s_LedActivePin[i]);
    }
}


void Led7Seg_OutSeg(u8 iCode)
{
    u8 ledDecode = iCode;
    u8 i;
    for (i=0; i<TOTAL_SEGMENT; i++)
    {
        if (0 < (ledDecode & 0x01))
        {
            GPIO_WriteLow(s_SegmentPort[i], s_SegmentPin[i]);
        }
        else
        {
            GPIO_WriteHigh(s_SegmentPort[i], s_SegmentPin[i]);
        }
        ledDecode >>= 1;
    }
}


void Led7Seg_SetDispAll(bool iDisp)
{
    s_DispAllSeg = iDisp;
}


void Led7Seg_SetDispDp(bool iDispDp)
{
    s_DispSegDp = iDispDp;
}


bool Led7Seg_GetDispDp(void)
{
    return (s_DispSegDp);
}


void Led7Seg_Push(u16 iVal)
{
    u8 temp = iVal % 100;

    s_Led7SegDecoded[LED_TRAM]  = c_LedDecode[(iVal / 100) & 0x0F];
    s_Led7SegDecoded[LED_CHUC]  = c_LedDecode[temp / 10];
    s_Led7SegDecoded[LED_DONVI] = c_LedDecode[temp % 10];
    s_Led7SegDecoded[LED_REV]   = c_LedDecode[0];

    s_CurActiveIndex = 0;
}


void SW_Process(u8 bntIndex)
{
    s_SWPressed[bntIndex] = (RESET == GPIO_ReadInputPin(SW_IN_PORT, (GPIO_Pin_TypeDef)SW_IN_PIN))? TRUE: FALSE;
    switch (bntIndex)
    {
    case BNT_MODE:
        {
            if (TRUE == s_SWPressed[BNT_MODE] && s_SWPressedOld[BNT_MODE] != s_SWPressed[BNT_MODE])
            {
                PWM_ChangeMode();
            }
            s_SWPressedOld[BNT_MODE] = s_SWPressed[BNT_MODE];
        } break;

    case BNT_INC:
        {
            if (TRUE == s_SWPressed[BNT_INC] && s_SWPressedOld[BNT_INC] != s_SWPressed[BNT_INC])
            {
                PWM_IncFreq();
            }
            s_SWPressedOld[BNT_INC] = s_SWPressed[BNT_INC];
        } break;

    case BNT_DEC:
        {
            if (TRUE == s_SWPressed[BNT_DEC] && s_SWPressedOld[BNT_DEC] != s_SWPressed[BNT_DEC])
            {
                PWM_DecFreq();
            }
            s_SWPressedOld[BNT_DEC] = s_SWPressed[BNT_DEC];
        } break;
    }
}


void Led7Seg_RunOne(void)
{
    u8 ledCode;

    if (TRUE == s_Led7Seg_IntFlag)
    {
        s_Led7Seg_IntFlag = FALSE; 

        // get SW status
        if (LED_REV != s_CurActiveIndex)
        {
            Led7Seg_SetLedOFF(LED_REV);
        }
        SW_Process(s_CurActiveIndex);

        // off all led
        Led7Seg_SetAllLedOFF();

        // Check and inc display loop
        if (TOTAL_ACTIVE_LED <= ++s_CurActiveIndex)
        {
            s_CurActiveIndex = 0;
        }

        // prepare next active led
        //if ( (FALSE == s_DispAllSeg) || ( (LED_TRAM == s_CurActiveIndex) && (c_LedDecode[0] == s_Led7SegDecoded[s_CurActiveIndex]) ) )
        if (FALSE == s_DispAllSeg)
        {
            ledCode = ALL_SEG_DISABLE;
        }
        else
        {
            ledCode = s_Led7SegDecoded[s_CurActiveIndex];
        }
        
        if (TRUE == s_DispSegDp && LED_CHUC == s_CurActiveIndex)
        {
            ledCode |= SEG_DP_ENABLE;
        }

        // Display next active led
        Led7Seg_OutSeg(ledCode);
        Led7Seg_SetLedON(s_CurActiveIndex);
    }
}
